package com.dmbjz.webdemo.config;

import com.dmbjz.webdemo.entity.Person;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;

/**
 * 将结果转换为Yaml的转换器
 */
@Slf4j
public class MyYamlHttpMessageConverter extends AbstractHttpMessageConverter<Object> {

    //把对象转成yaml
    private ObjectMapper objectMapper = null;

    public MyYamlHttpMessageConverter() {

        //告诉 SpringBoot 这个 MessageConverter支持哪种媒体类型。type 是 / 之前的，subtype 是 / 之后的
        super(new MediaType("text", "yaml", Charset.forName("UTF-8")));

        //禁用转换为 YAML 后输出的 --- 横线
        YAMLFactory yamlFactory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
        this.objectMapper = new ObjectMapper(yamlFactory);

    }


    /**
     * 限制转换器能够处理的返回类型
     */
    @Override
    protected boolean supports(Class<?> clazz) {
        //限制返回结果只有为 Persion 类时才能返回 YAML 数据。如果不是 Person 类型，则不支持，会返回空结果
        return Person.class.equals(clazz);
    }


    //如果supports(Class<?>)方法返回为true，则该方法才可能被触发。重写该方法以便从HTTP请求的 Body 部分提取数据进行真正的数据对象转换
    @Override
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }


    /**
     * 负责将被 @ResponseBody 标记的方法返回的结果（或者报错结果），转换为既定的数据格式返回给本次 HTTP 请求的调用者
     *
     * @param methodReturnValue 方法返回值
     * @param outputMessage     相应输出流
     */
    @Override
    protected void writeInternal(Object methodReturnValue, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

        //try-with写法，自动关流
        try (OutputStream os = outputMessage.getBody()) {
            this.objectMapper.writeValue(os, methodReturnValue);
        }

    }


}